﻿using System;
using System.Drawing;
using System.Windows.Forms;
using AForge.Video;
using AForge.Video.DirectShow;
using AForge.Vision.Motion;
using System.Collections.Generic;
using System.Windows.Forms.DataVisualization.Charting;
using System.Threading;

namespace Analizador_de_Semillas
{
    public partial class MainForm : Form
    {
        static FilterInfoCollection camara;
        static VideoCaptureDevice capturaUno = null;
        static VideoCaptureDevice capturaDos = null;
        static MotionDetector detectorUno = new MotionDetector(new SimpleBackgroundModelingDetector()
            , new BlobCountingObjectsProcessing());
        static MotionDetector detectorDos = new MotionDetector(new SimpleBackgroundModelingDetector()
            , new BlobCountingObjectsProcessing());
        static double[] x = new double[256];

        delegate void setCallBackGraficos(Series r, Series a, Series v);
        delegate void setCallBackEtiquetas(double[] v);
        delegate void setCallBackAvg(double[] v);

        public MainForm()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            camara = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (camara.Count == 0)
            {
                MessageBox.Show("No hay dispositivos disponibles!!", "Alerta", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                this.Close();
            }
            else
            {

                capturaUno = new VideoCaptureDevice(camara[0].MonikerString);

                videoSource.VideoSource = new AsyncVideoSource(capturaUno);
                videoSource.Start();

                capturaDos = new VideoCaptureDevice(camara[1].MonikerString);

                videoSourceUno.VideoSource = new AsyncVideoSource(capturaDos);
                videoSourceUno.Start();

                for (int i = 0; i < 256; i++)
                {
                    x[i] = i;
                }
            }
        }

        private void videoSource_NewFrame(object sender, ref Bitmap image)
        {
            lock (this)
            {
                if (detectorUno != null && detectorDos != null)
                {
                    float motionLevel = detectorUno.ProcessFrame(image);

                    if (motionLevel > 0.2)
                    {
                        // check objects' count
                       BlobCountingObjectsProcessing countingDetector = (BlobCountingObjectsProcessing) detectorUno.MotionProcessingAlgorithm;
                       BlobCountingObjectsProcessing countingDetectorDos = (BlobCountingObjectsProcessing)detectorDos.MotionProcessingAlgorithm;

                       if (countingDetector.ObjectsCount > 0 && countingDetectorDos.ObjectsCount > 0)
                       {
                           picImagenUno.BackgroundImage = videoSource.GetCurrentVideoFrame();

                           pctImagenDos.BackgroundImage = videoSourceUno.GetCurrentVideoFrame();

                           double[] sizes = Analizador.GetAvgSize(countingDetector, countingDetectorDos);

                           double[] porcs = Analizador.GetPercentColor((Bitmap)picImagenUno.BackgroundImage, (Bitmap)pctImagenDos.BackgroundImage);

                           CargarEtiquetas(sizes);

                           CargarPorcentajes(porcs);
                        }
                    }
                }
            }
        }

        private void videoSourceUno_NewFrame(object sender, ref Bitmap image)
        {
            lock (this)
            {
                if (detectorUno != null && detectorDos != null)
                {
                    float motionLevel = detectorDos.ProcessFrame(image);

                    if (motionLevel > 0.2)
                    {
                        // check objects' count
                        BlobCountingObjectsProcessing countingDetector = (BlobCountingObjectsProcessing)detectorUno.MotionProcessingAlgorithm;
                        BlobCountingObjectsProcessing countingDetectorDos = (BlobCountingObjectsProcessing)detectorDos.MotionProcessingAlgorithm;

                        if (countingDetector.ObjectsCount > 0 && countingDetectorDos.ObjectsCount > 0)
                        {
                            picImagenUno.BackgroundImage = videoSource.GetCurrentVideoFrame();

                            pctImagenDos.BackgroundImage = videoSourceUno.GetCurrentVideoFrame();

                            double[] sizes = Analizador.GetAvgSize(countingDetector, countingDetectorDos);

                            double[] porcs = Analizador.GetPercentColor((Bitmap)picImagenUno.BackgroundImage,(Bitmap)pctImagenDos.BackgroundImage);

                            CargarEtiquetas(sizes);

                            CargarPorcentajes(porcs);

                        }
                    }
                }
            }
        }

        private void pctImagen_BackgroundImageChanged(object sender, EventArgs e)
        {
            if (picImagenUno.BackgroundImage != null && pctImagenDos.BackgroundImage != null)
            {
                try
                {
                    List<double[]> datos = Analizador.CargarHistograma((Bitmap)pctImagenDos.BackgroundImage, (Bitmap)picImagenUno.BackgroundImage);

                    Series rojo = new Series();
                    Series azul = new Series();
                    Series verde = new Series();

                    for (int i = 0; i < 256; i++)
                    {
                        rojo.Points.AddXY(x[i], datos[0][i]);

                        azul.Points.AddXY(x[i], datos[1][i]);

                        verde.Points.AddXY(x[i], datos[2][i]);
                    }

                    CargarGrafico(rojo, azul, verde);
                }
                catch (Exception)
                {


                }
            }

        }

        private void CargarGrafico(Series rojo, Series azul, Series verde)
        {
            if (chrHistogramaRojo.InvokeRequired)
            {
                setCallBackGraficos call = new setCallBackGraficos(CargarGrafico);
                this.Invoke(call, new object[] { rojo, azul, verde });
            }
            else
            {
                if (chrHistogramaRojo.Series.Count > 0) chrHistogramaRojo.Series.Clear();
                chrHistogramaRojo.Series.Add(rojo);
                chrHistogramaRojo.Series[0].Color = Color.Red;
                
            }

            if (chrHistogramaAzul.InvokeRequired)
            {
                setCallBackGraficos call = new setCallBackGraficos(CargarGrafico);
                this.Invoke(call, new object[] { rojo, azul, verde });
            }
            else
            {
                if (chrHistogramaAzul.Series.Count > 0) chrHistogramaAzul.Series.Clear();
                chrHistogramaAzul.Series.Add(azul);
                chrHistogramaAzul.Series[0].Color = Color.Blue;
            }

            if (chrHistogramaVerde.InvokeRequired)
            {
                setCallBackGraficos call = new setCallBackGraficos(CargarGrafico);
                this.Invoke(call, new object[] { rojo, azul, verde });
            }
            else
            {
                if (chrHistogramaVerde.Series.Count > 0) chrHistogramaVerde.Series.Clear();
                chrHistogramaVerde.Series.Add(verde);
                chrHistogramaVerde.Series[0].Color = Color.Green;
            }
        }

        public void CargarPorcentajes(double[] valores)
        {
            if (lblPorcR.InvokeRequired)
            {
                setCallBackAvg c = new setCallBackAvg(CargarPorcentajes);
                this.Invoke(c, new object[] { valores });
            }
            else
            {
                lblPorcR.Text = valores[0].ToString();
                lblPorcB.Text = valores[1].ToString();
                lblPorcG.Text = valores[2].ToString();
                //EscribirTexto.escribirArchivo(valores[2].ToString(), valores[1].ToString(), valores[0].ToString());
            }

            if (lblPorcB.InvokeRequired)
            {
                setCallBackAvg c = new setCallBackAvg(CargarPorcentajes);
                this.Invoke(c, new object[] { valores });
            }
            else
            {
                lblPorcR.Text = valores[0].ToString();
                lblPorcB.Text = valores[1].ToString();
                lblPorcG.Text = valores[2].ToString();
                //EscribirTexto.escribirArchivo(valores[2].ToString(), valores[1].ToString(), valores[0].ToString());
            }

            if (lblPorcG.InvokeRequired)
            {
                setCallBackAvg c = new setCallBackAvg(CargarPorcentajes);
                this.Invoke(c, new object[] { valores });
            }
            else
            {
                lblPorcR.Text = valores[0].ToString();
                lblPorcB.Text = valores[1].ToString();
                lblPorcG.Text = valores[2].ToString();
                //EscribirTexto.escribirArchivo(valores[2].ToString(), valores[1].ToString(), valores[0].ToString());
            }
        }

        public void CargarEtiquetas(double[] valores)
        {
            if (lblObjetos.InvokeRequired)
            {
                setCallBackEtiquetas c = new setCallBackEtiquetas(CargarEtiquetas);
                this.Invoke(c, new object[] { valores });
            }
            else
            {
                lblObjetos.Text = valores[2].ToString();
                lblWidth.Text = valores[1].ToString();
                lblHeight.Text = valores[0].ToString();
                EscribirTexto.escribirArchivo(valores[2].ToString(), valores[1].ToString(), valores[0].ToString());
            }

            if (lblHeight.InvokeRequired)
            {
                setCallBackEtiquetas c = new setCallBackEtiquetas(CargarEtiquetas);
                this.Invoke(c, new object[] { valores });
            }
            else
            {
                lblObjetos.Text = valores[2].ToString();
                lblWidth.Text = valores[1].ToString();
                lblHeight.Text = valores[0].ToString();
                EscribirTexto.escribirArchivo(valores[2].ToString(), valores[1].ToString(), valores[0].ToString());
            }

            if (lblWidth.InvokeRequired)
            {
                setCallBackEtiquetas c = new setCallBackEtiquetas(CargarEtiquetas);
                this.Invoke(c, new object[] { valores });
            }
            else
            {
                lblObjetos.Text = valores[2].ToString();
                lblWidth.Text = valores[1].ToString();
                lblHeight.Text = valores[0].ToString();
                EscribirTexto.escribirArchivo(valores[2].ToString(), valores[1].ToString(), valores[0].ToString());
            }
        }

        private void CerrarCamaras()
        {
            videoSource.SignalToStop();
            videoSourceUno.SignalToStop();
            videoSourceUno.WaitForStop();
            videoSource.WaitForStop();

            if (detectorUno != null)
            {
                detectorUno.Reset();
            }

            if (detectorDos != null)
            {
                detectorDos.Reset();
            }

            this.Dispose();
            this.Close();
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            CerrarCamaras();
        }
    }
}
